package org.abacus.hibernate;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 * @author chaoyang.li
 */
public class HibernateTransactionStrategy implements TransactionStrategy {
	private static final ThreadLocal<TransactionStrategy> instance = new ThreadLocal<TransactionStrategy>();
	private List<Transaction> txs;

	/**
	 * @author chaoyang.li
	 */
	protected HibernateTransactionStrategy() {
		super();
		txs = new ArrayList<Transaction>();
	}

	/**
	 * @author chaoyang.li
	 */
	public static TransactionStrategy getInstance() {
		if (instance.get() == null) {
			instance.set(new HibernateTransactionStrategy());
		}
		return instance.get();
	}

	/**
	 * @author chaoyang.li
	 */
	public void begin() {
		try {
			for (String tag : HibernateSessionProvider.getTags()) {
				txs.add(begin(HibernateSessionProvider.getCurrentSession(tag)));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @author chaoyang.li
	 */
	public void commit() {
		try {
			for (Transaction tx : txs) {
				commit(tx);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @author chaoyang.li
	 */
	public void rollback() {
		try {
			for (Transaction tx : txs) {
				rollback(tx);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @author chaoyang.li
	 */
	public void clearCache() {
		try {
			for (String tag : HibernateSessionProvider.getTags()) {
				Session session = HibernateSessionProvider.getCurrentSession(tag);
				clearCache(session);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @author chaoyang.li
	 * @param tag
	 */
	public void begin(String tag) {
		try {
			begin(HibernateSessionProvider.getCurrentSession(tag));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @author chaoyang.li
	 * @param tag
	 */
	public void commit(String tag) {
		try {
			Transaction tx = HibernateSessionProvider.getCurrentSession(tag).getTransaction();
			commit(tx);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @author chaoyang.li
	 * @param tag
	 */
	public void rollback(String tag) {
		try {
			Transaction tx = HibernateSessionProvider.getCurrentSession(tag).getTransaction();
			rollback(tx);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @author chaoyang.li
	 * @param tag
	 */
	public void clearCache(String tag) {
		try {
			Session session = HibernateSessionProvider.getCurrentSession(tag);
			clearCache(session);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * @author chaoyang.li
	 * @param session
	 */
	protected Transaction begin(Session session) {
		Transaction tx = null;
		if (null != session) {
			tx = session.beginTransaction();
		}
		return tx;
	}

	/**
	 * @author chaoyang.li
	 * @param tx
	 */
	protected void commit(Transaction tx) {
		if (null != tx) {
			tx.commit();
		}
	}

	/**
	 * @author chaoyang.li
	 * @param tx
	 */
	protected void rollback(Transaction tx) {
		if (null != tx && tx.isActive()) {
			tx.rollback();
		}
	}

	/**
	 * @author chaoyang.li
	 * @param session
	 */
	protected void clearCache(Session session) {
		if (null != session) {
			session.flush();
			session.clear();
		}
	}
}
